﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace Twillo.Core.Settings
{
    internal static class EncryptionProvider
    {
        internal static string ByteArrayToString(byte[] bytes)
        {
            return Convert.ToBase64String(bytes);
        }

        internal static string Decode(byte[] Bytes, EncryptionProviderType Provider)
        {
            ICryptoTransform cryptoTransform = null;
            switch (((int)Provider))
            {
                case 2:
                    cryptoTransform = new DESCryptoServiceProvider().CreateDecryptor(GetKey(Provider), GetIV(Provider));
                    return Decrypt(Bytes, cryptoTransform);

                case 3:
                    cryptoTransform = new TripleDESCryptoServiceProvider().CreateDecryptor(GetKey(Provider), GetIV(Provider));
                    return Decrypt(Bytes, cryptoTransform);

                case 4:
                    cryptoTransform = new RC2CryptoServiceProvider().CreateDecryptor(GetKey(Provider), GetIV(Provider));
                    return Decrypt(Bytes, cryptoTransform);

                case 5:
                    cryptoTransform = Rijndael.Create().CreateDecryptor(GetKey(Provider), GetIV(Provider));
                    return Decrypt(Bytes, cryptoTransform);

                case 6:
                    {
                        byte[] hashedTextInBytes = new RSACryptoServiceProvider().Decrypt(Bytes, false);
                        return Encoding.UTF8.GetString(hashedTextInBytes);
                    }
            }
            return null;
        }

        internal static string Decode1(string InputString, EncryptionProviderType Provider)
        {
            try
            {
                return Decode(StringToByteArray(InputString), Provider);
            }
            catch
            {
                return "";
            }
        }

        internal static string Decrypt(byte[] inputInBytes, ICryptoTransform cryptoTransform)
        {
            UTF8Encoding utf8encoder = new UTF8Encoding();
            MemoryStream decryptedStream = new MemoryStream();
            CryptoStream cryptStream = new CryptoStream(decryptedStream, cryptoTransform, CryptoStreamMode.Write);
            cryptStream.Write(inputInBytes, 0, inputInBytes.Length);
            cryptStream.FlushFinalBlock();
            decryptedStream.Position = 0L;
            byte[] result = new byte[((int)(decryptedStream.Length - 1L)) + 1];
            decryptedStream.Read(result, 0, (int)decryptedStream.Length);
            cryptStream.Close();
            return utf8encoder.GetString(result);
        }

        internal static byte[] Encode(string InputString, EncryptionProviderType Provider)
        {
            ICryptoTransform cryptoTransform = null;
            switch (((int)Provider))
            {
                case 2:
                    cryptoTransform = new DESCryptoServiceProvider().CreateEncryptor(GetKey(Provider), GetIV(Provider));
                    return Encrypt(InputString, cryptoTransform);

                case 3:
                    cryptoTransform = new TripleDESCryptoServiceProvider().CreateEncryptor(GetKey(Provider), GetIV(Provider));
                    return Encrypt(InputString, cryptoTransform);

                case 4:
                    cryptoTransform = new RC2CryptoServiceProvider().CreateEncryptor(GetKey(Provider), GetIV(Provider));
                    return Encrypt(InputString, cryptoTransform);

                case 5:
                    cryptoTransform = Rijndael.Create().CreateEncryptor(GetKey(Provider), GetIV(Provider));
                    return Encrypt(InputString, cryptoTransform);

                case 6:
                    {
                        RSACryptoServiceProvider enc = new RSACryptoServiceProvider();
                        byte[] inBytes = new UTF8Encoding().GetBytes(InputString);
                        return enc.Encrypt(inBytes, false);
                    }
            }
            return null;
        }

        internal static string Encode1(string InputString, EncryptionProviderType Provider)
        {
            byte[] Bytes = null;
            Bytes = Encode(InputString, Provider);
            if (Bytes == null)
            {
                return string.Empty;
            }
            return ByteArrayToString(Bytes);
        }

        internal static byte[] Encrypt(string plainText, ICryptoTransform cryptoTransform)
        {
            byte[] inputInBytes = new UTF8Encoding().GetBytes(plainText);
            MemoryStream encryptedStream = new MemoryStream();
            CryptoStream cryptStream = new CryptoStream(encryptedStream, cryptoTransform, CryptoStreamMode.Write);
            cryptStream.Write(inputInBytes, 0, inputInBytes.Length);
            cryptStream.FlushFinalBlock();
            encryptedStream.Position = 0L;
            byte[] result = new byte[((int)(encryptedStream.Length - 1L)) + 1];
            encryptedStream.Read(result, 0, (int)encryptedStream.Length);
            cryptStream.Close();
            return result;
        }

        internal static byte[] GetIV(EncryptionProviderType Provider)
        {
            byte[] iv = new byte[] { 0x41, 110, 0x44, 0x1a, 0x45, 0xb2, 200, 0xdb };
            byte[] RijndaelIV = new byte[] { 0x41, 110, 0x44, 0x1a, 0x45, 0xb2, 200, 0xdb, 0x41, 110, 0x44, 0x1a, 0x45, 0xb2, 200, 0xdb };
            switch (((int)Provider))
            {
                case 2:
                case 3:
                case 4:
                    return iv;

                case 5:
                    return RijndaelIV;
            }
            return null;
        }

        internal static byte[] GetKey(EncryptionProviderType Provider)
        {
            byte[] tripleDESkey = new byte[] { 
            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0x10, 
            0x11, 0x12, 0x13, 20, 0x15, 0x16, 0x17, 0x18
         };
            byte[] RijndaelKey = new byte[] { 
            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0x10, 
            0x11, 0x12, 0x13, 20, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 30, 0x1f, 0x20
         };
            byte[] RC2Key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0x10 };
            byte[] DESkey = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
            switch (((int)Provider))
            {
                case 2:
                    return DESkey;

                case 3:
                    return tripleDESkey;

                case 4:
                    return RC2Key;

                case 5:
                    return RijndaelKey;
            }
            return null;
        }

        internal static byte[] MD5Hash(string Value)
        {
            byte[] buff = new UnicodeEncoding().GetBytes(Value);
            MD5CryptoServiceProvider enc = new MD5CryptoServiceProvider();
            return enc.ComputeHash(buff);
        }

        internal static string MD5Hash1(string Value)
        {
            byte[] buff = new UnicodeEncoding().GetBytes(Value);
            MD5CryptoServiceProvider enc = new MD5CryptoServiceProvider();
            return ByteArrayToString(enc.ComputeHash(buff));
        }

        internal static byte[] StringToByteArray(string InputString)
        {
            return Convert.FromBase64String(InputString);
        }

    }

    internal enum EncryptionProviderType
    {
        DES = 2,
        RC2 = 4,
        Rijndael = 5,
        RSA = 6,
        TripleDES = 3
    }

}
